"""
提供者系统

定义依赖注入的提供者类型，负责创建和管理对象实例。
"""

from abc import ABC, abstractmethod
from typing import Any, Callable, Type, TypeVar, Dict, List, Optional
import inspect

T = TypeVar('T')


class Provider(ABC):
    """
    提供者抽象基类
    
    定义如何创建和提供对象实例的接口。
    """
    
    @abstractmethod
    def provide(self, injector) -> Any:
        """
        提供对象实例
        
        Args:
            injector: 依赖注入容器
        
        Returns:
            对象实例
        """
        pass
    
    @abstractmethod
    def get_dependencies(self) -> List['Token']:
        """获取依赖列表"""
        pass


class ClassProvider(Provider):
    """
    类提供者
    
    通过类构造函数创建实例。
    """
    
    def __init__(self, cls: Type[T], *args, **kwargs):
        self.cls = cls
        self.args = args
        self.kwargs = kwargs
        self._dependencies = self._analyze_dependencies()
    
    def provide(self, injector) -> T:
        """通过类构造函数创建实例"""
        # 解析构造函数参数
        resolved_kwargs = self._resolve_dependencies(injector)
        resolved_kwargs.update(self.kwargs)

        return self.cls(*self.args, **resolved_kwargs)

    def get_dependencies(self) -> List['Token']:
        """获取类的依赖"""
        return self._dependencies

    def _analyze_dependencies(self) -> List['Token']:
        """分析类的依赖"""
        from .tokens import Token, create_token

        dependencies = []

        # 获取构造函数签名
        sig = inspect.signature(self.cls.__init__)

        for param_name, param in sig.parameters.items():
            if param_name == 'self':
                continue

            # 检查是否有注入标记
            if hasattr(param, 'default') and hasattr(param.default, 'token'):
                dependencies.append(param.default.token)
            elif param.annotation != inspect.Parameter.empty:
                # 使用类型注解作为Token
                dependencies.append(create_token(param.annotation))

        return dependencies

    def _resolve_dependencies(self, injector) -> Dict[str, Any]:
        """解析依赖参数"""
        resolved = {}

        # 获取构造函数签名
        sig = inspect.signature(self.cls.__init__)

        for param_name, param in sig.parameters.items():
            if param_name == 'self':
                continue

            # 跳过已提供的参数
            if param_name in self.kwargs:
                continue

            # 检查是否有注入标记
            if hasattr(param, 'default') and hasattr(param.default, 'token'):
                token = param.default.token
                resolved[param_name] = injector.get(token)
            elif param.annotation != inspect.Parameter.empty:
                # 使用类型注解作为Token
                from .tokens import create_token
                token = create_token(param.annotation)
                try:
                    resolved[param_name] = injector.get(token)
                except KeyError:
                    # 如果没有注册，检查是否有默认值
                    if param.default != inspect.Parameter.empty:
                        resolved[param_name] = param.default
                    else:
                        raise

        return resolved


class FactoryProvider(Provider):
    """
    工厂提供者
    
    通过工厂函数创建实例。
    """
    
    def __init__(self, factory: Callable[..., T], *args, **kwargs):
        self.factory = factory
        self.args = args
        self.kwargs = kwargs
        self._dependencies = self._analyze_dependencies()
    
    def provide(self, injector) -> T:
        """通过工厂函数创建实例"""
        resolved_kwargs = self._resolve_dependencies(injector)
        resolved_kwargs.update(self.kwargs)

        return self.factory(*self.args, **resolved_kwargs)

    def get_dependencies(self) -> List['Token']:
        """获取工厂函数的依赖"""
        return self._dependencies

    def _analyze_dependencies(self) -> List['Token']:
        """分析工厂函数的依赖"""
        from .tokens import Token, create_token

        dependencies = []

        # 获取工厂函数签名
        sig = inspect.signature(self.factory)

        for param_name, param in sig.parameters.items():
            # 检查是否有注入标记
            if hasattr(param, 'default') and hasattr(param.default, 'token'):
                dependencies.append(param.default.token)
            elif param.annotation != inspect.Parameter.empty:
                # 使用类型注解作为Token
                dependencies.append(create_token(param.annotation))

        return dependencies

    def _resolve_dependencies(self, injector) -> Dict[str, Any]:
        """解析依赖参数"""
        resolved = {}
        
        # 获取工厂函数签名
        sig = inspect.signature(self.factory)
        
        for param_name, param in sig.parameters.items():
            # 跳过已提供的参数
            if param_name in self.kwargs:
                continue
            
            # 检查是否有注入标记
            if hasattr(param, 'default') and hasattr(param.default, 'token'):
                token = param.default.token
                resolved[param_name] = injector.get(token)
            elif param.annotation != inspect.Parameter.empty:
                # 使用类型注解作为Token
                from .tokens import create_token
                token = create_token(param.annotation)
                try:
                    resolved[param_name] = injector.get(token)
                except KeyError:
                    # 如果没有注册，检查是否有默认值
                    if param.default != inspect.Parameter.empty:
                        resolved[param_name] = param.default
                    else:
                        raise
        
        return resolved


class ValueProvider(Provider):
    """
    值提供者
    
    直接提供预创建的实例。
    """
    
    def __init__(self, value: T):
        self.value = value
    
    def provide(self, injector) -> T:
        """直接返回值"""
        return self.value

    def get_dependencies(self) -> List['Token']:
        """值提供者没有依赖"""
        return []


class SingletonProvider(Provider):
    """
    单例提供者

    确保只创建一个实例的提供者装饰器。
    """

    def __init__(self, provider: Provider):
        self.provider = provider
        self._instance = None
        self._created = False

    def provide(self, injector) -> Any:
        """提供单例实例"""
        if not self._created:
            self._instance = self.provider.provide(injector)
            self._created = True
        return self._instance

    def get_dependencies(self) -> List['Token']:
        """获取被装饰提供者的依赖"""
        return self.provider.get_dependencies()


class LazyProvider(Provider):
    """
    懒加载提供者

    延迟创建实例直到第一次访问。
    """

    def __init__(self, provider: Provider):
        self.provider = provider
        self._instance = None
        self._created = False

    def provide(self, injector) -> Any:
        """懒加载实例"""
        if not self._created:
            self._instance = self.provider.provide(injector)
            self._created = True
        return self._instance

    def get_dependencies(self) -> List['Token']:
        """获取被装饰提供者的依赖"""
        return self.provider.get_dependencies()


class ConditionalProvider(Provider):
    """
    条件提供者

    根据条件选择不同的提供者。
    """

    def __init__(self, condition: Callable[[Any], bool],
                 true_provider: Provider, false_provider: Provider):
        self.condition = condition
        self.true_provider = true_provider
        self.false_provider = false_provider

    def provide(self, injector) -> Any:
        """根据条件提供实例"""
        if self.condition(injector):
            return self.true_provider.provide(injector)
        else:
            return self.false_provider.provide(injector)

    def get_dependencies(self) -> List['Token']:
        """获取所有可能提供者的依赖"""
        dependencies = []
        dependencies.extend(self.true_provider.get_dependencies())
        dependencies.extend(self.false_provider.get_dependencies())
        return list(set(dependencies))  # 去重


class ChainProvider(Provider):
    """
    链式提供者

    按顺序尝试多个提供者，直到成功。
    """

    def __init__(self, providers: List[Provider]):
        self.providers = providers

    def provide(self, injector) -> Any:
        """链式尝试提供实例"""
        last_error = None

        for provider in self.providers:
            try:
                return provider.provide(injector)
            except Exception as e:
                last_error = e
                continue

        # 所有提供者都失败
        raise RuntimeError(f"所有提供者都失败，最后错误: {last_error}")

    def get_dependencies(self) -> List['Token']:
        """获取所有提供者的依赖"""
        dependencies = []
        for provider in self.providers:
            dependencies.extend(provider.get_dependencies())
        return list(set(dependencies))  # 去重


class ProviderRegistry:
    """
    提供者注册表
    
    管理不同类型的提供者。
    """
    
    def __init__(self):
        self._providers: Dict[str, Type[Provider]] = {}
        self._register_default_providers()
    
    def _register_default_providers(self) -> None:
        """注册默认提供者"""
        self.register("class", ClassProvider)
        self.register("factory", FactoryProvider)
        self.register("value", ValueProvider)
        self.register("singleton", SingletonProvider)
        self.register("lazy", LazyProvider)
        self.register("conditional", ConditionalProvider)
        self.register("chain", ChainProvider)
    
    def register(self, name: str, provider_class: Type[Provider]) -> None:
        """注册提供者类型"""
        self._providers[name] = provider_class
    
    def get(self, name: str) -> Optional[Type[Provider]]:
        """获取提供者类型"""
        return self._providers.get(name)
    
    def create(self, name: str, *args, **kwargs) -> Optional[Provider]:
        """创建提供者实例"""
        provider_class = self.get(name)
        if provider_class:
            return provider_class(*args, **kwargs)
        return None
    
    def list_providers(self) -> List[str]:
        """列出所有提供者类型"""
        return list(self._providers.keys())
    
    def unregister(self, name: str) -> bool:
        """注销提供者类型"""
        if name in self._providers:
            del self._providers[name]
            return True
        return False


# 全局提供者注册表
provider_registry = ProviderRegistry()


# 便捷函数
def class_provider(cls: Type[T], *args, **kwargs) -> ClassProvider:
    """创建类提供者"""
    return ClassProvider(cls, *args, **kwargs)


def factory_provider(factory: Callable[..., T], *args, **kwargs) -> FactoryProvider:
    """创建工厂提供者"""
    return FactoryProvider(factory, *args, **kwargs)


def value_provider(value: T) -> ValueProvider:
    """创建值提供者"""
    return ValueProvider(value)


def singleton_provider(provider: Provider) -> SingletonProvider:
    """创建单例提供者"""
    return SingletonProvider(provider)


def lazy_provider(provider: Provider) -> LazyProvider:
    """创建懒加载提供者"""
    return LazyProvider(provider)
